package com.mocha.bss.generator;

import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.util.Collections;
import java.util.Properties;

/**
 * @author yangziyang
 * @since 2025/3/17
 */

@Data
public class CodeGenerator {

    private String projectDir;

    private String url;

    private String username;

    private String password;

    private String author;

    private String packageName;

    private String service;

    private String repository;

    private String entity;

    private String mapper;

    private String xml;

    private Boolean hasSuperEntity = Boolean.TRUE;

    private String[] superEntityColumns = {"tenant_id", "creator_id", "create_time", "updater_id", "update_time", "status_bit"};

    private String[] includeTables = {};

    private String[] tablePrefix = {};

    public void gen() {
        this.initialization();
        FastAutoGenerator.create(url, username, password)
                .dataSourceConfig(builder -> builder
                        .dbQuery(new MySqlQuery())
                        .typeConvert(new MySqlTypeConvert())
                        .typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                            DbColumnType columnType = (DbColumnType) typeRegistry.getColumnType(metaInfo);
                            if (columnType == DbColumnType.BYTE) return DbColumnType.INTEGER;
                            return columnType;
                        }))
                .globalConfig(builder -> builder
                        .author(author)
                        .outputDir(projectDir)
                        .disableOpenDir()
                        .dateType(DateType.ONLY_DATE)
                        .commentDate("yyyy-MM-dd")
                ).packageConfig(builder -> builder
                        .parent(packageName)
                        .service("service")
                        .serviceImpl("repository")
                        .entity("repository.entity")
                        .mapper("repository.mapper")
                        .xml("repository.xml")
                        .pathInfo(Collections.singletonMap(OutputFile.controller, null))
                ).strategyConfig(builder -> {
                    builder.addInclude(includeTables).addTablePrefix(tablePrefix);
                    builder.controllerBuilder().disable();
                    builder.serviceBuilder().formatServiceFileName("%sService").serviceTemplate(service).superServiceImplClass("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl").formatServiceImplFileName("%sRepository").serviceImplTemplate(repository);
                    if (hasSuperEntity) builder.entityBuilder().superClass("com.coffee.mybatis.TenantEntity").addSuperEntityColumns(superEntityColumns);
                    builder.entityBuilder().enableFileOverride().enableLombok().enableChainModel().idType(IdType.AUTO).formatFileName("%sEntity").javaTemplate(entity);
                    builder.mapperBuilder().superClass("com.baomidou.mybatisplus.core.mapper.BaseMapper").mapperTemplate(mapper).formatMapperFileName("%sMapper").formatXmlFileName("%sMapper").mapperXmlTemplate(xml);
                }).templateEngine(new FreemarkerTemplateEngine()).execute();
    }

    private void initialization() {
        Properties props = getProperties();
        projectDir = this.getOutputDir(props.getProperty("filePath"));
        if (StringUtils.isBlank(url)) url = props.getProperty("url");
        if (StringUtils.isBlank(username)) username = props.getProperty("username");
        if (StringUtils.isBlank(password)) password = props.getProperty("password");
        if (StringUtils.isBlank(author)) author = props.getProperty("author");
        if (StringUtils.isBlank(packageName)) packageName = props.getProperty("packageName");
        service = props.getProperty("service");
        repository = props.getProperty("repository");
        entity = props.getProperty("entity");
        mapper = props.getProperty("mapper");
        xml = props.getProperty("xml");
    }

    private Properties getProperties() {
        Resource resource = new ClassPathResource("/template/code.properties");
        Properties props = new Properties();
        try {
            props = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return props;
    }

    public String getOutputDir(String filePath) {
        return (StringUtils.isBlank(projectDir) ? System.getProperty("user.dir") : projectDir) + filePath;
    }

    public static CodeGenerator getInstance() {
        return GeneratorHolder.INSTANCE;
    }

    private static class GeneratorHolder {
        private static CodeGenerator INSTANCE = new CodeGenerator();
    }
}
